<?php

/**
 * Transform numberID
 * @author hopes@2015.11.26
 */
class alphaId
{
    /**
     * index
     * @var string
     */
    private $index = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789zyxwvutsrqponmlkjihgfedcba';

    /**
     * power
     * @var integer
     */
    private $pow;

    /**
     * solt
     * @var string
     */
    private $solt;

    public function __construct($solt = NULL, $pow = NULL, $index = NULL)
    {
        $this->solt = $solt;
        $this->pow = $pow;
        $index && $this->index = $index;

        $this->_pretreatment();
    }

    /**
     * numberID to hashID
     * @param integer $id
     * @return string
     */
    public function getHash($id)
    {
        $string = NULL;

        $indexLen = strlen($this->index);

        if(is_numeric($this->pow))
        {
            $this->pow > 0 && $id += pow($indexLen, $this->pow);
        }

        for($i = floor(log($id, $indexLen)); $i >= 0; $i--)
        {
            $bcp = bcpow($indexLen, $i);
            $ibi = floor($id / $bcp) % $indexLen;
            $string .= substr($this->index, $ibi, 1);
            $id = $id - ($ibi * $bcp);
        }

        $string = strrev($string);

        return $string;
    }

    /**
     * hashID to numberID
     * @param string $string
     * @return integer
     */
    public function getNumber($string)
    {
        $id = 0;

        $indexLen = strlen($this->index);

        $string = strrev($string);
        $len = strlen($string) - 1;

        for($i = 0; $i <= $len; $i++)
        { 
            $bcp = bcpow($indexLen, $len - $i);
            $id = $id + strpos($this->index, substr($string, $i, 1)) * $bcp;
        }

        if(is_numeric($this->pow))
        {
            $this->pow && $id -= pow($indexLen, $this->pow);
        }

        $id = sprintf('%F', $id);
        $id = substr($id, 0, strpos($id, '.'));

        return $id;
    }

    /**
     * pretreatment
     */
    private function _pretreatment()
    {
        if($this->solt)
        {
            // index array
            $n = str_split($this->index);

            // solt array
            $indexLen = strlen($this->index);
            $soltHash = hash('sha256', $this->solt);
            (strlen($soltHash) < $indexLen) && $soltHash = hash('sha512', $this->solt);
            $soltHash = substr($soltHash, 0, $indexLen);
            $m = str_split($soltHash);

            // sort index by solt
            array_multisort($m, SORT_DESC, $n);
            $this->index = implode($n);
        }

        $this->pow && $this->pow--;
    }
}